<?php

namespace App\Libs;

use Exception;

class SimpleImage
{

    /**
     * 图片资源
     * @var
     */
    protected $image;

    /**
     * 图片类型
     * @var
     */
    protected $image_type;

    /**
     * 海报背景高度
     * @var
     */
    protected $backgroundHeight;

    /**
     * 海报背景宽度
     * @var
     */
    protected $backgroundWidth;

    /**
     * 字体颜色
     * @var string
     */
    protected $fontColor = "0,0,0";

    /**
     * 字体大小
     * @var string
     */
    protected $fontSize = "26";

    /**
     * 字体路径
     */
    protected $fontPath = "";

    /**
     * 图片资源是否可以保存
     * @var bool
     */
    protected $saveStatus = true;

    /**
     * 图片类型
     * @var
     */
    protected $mime;


    /**
     * @Title (读取图片)
     */
    public function load($filename)
    {

        $image_info       = getimagesize($filename);
        $this->mime       = $image_info["mime"];
        $this->image_type = $image_info[2];

        if($this->image_type==IMAGETYPE_JPEG){
            $this->image = @imagecreatefromjpeg($filename);
        }elseif($this->image_type==IMAGETYPE_GIF){

            $this->image = @imagecreatefromgif($filename);
        }elseif($this->image_type==IMAGETYPE_PNG){

            $this->image = @imagecreatefrompng($filename);
        }

        if(!$this->image){
            return false;
        }

        return $this;
    }


    /**
     * 图片切为圆形
     * @date (2022/4/11 17:34:09)
     * @author (WangDaBao)
     */
    public function fillet()
    {
        //	宽高
        $w = $this->getWidth();
        //	高
        $h = $this->getHeight();
        //
        $img = imagecreatetruecolor($w,$h);
        //	这一句一定要有
        imagesavealpha($img,true);
        //	拾取一个完全透明的颜色,最后一个参数127为全透明
        $bg = imagecolorallocatealpha($img,255,255,255,127);

        imagefill($img,0,0,$bg);

        $r   = $w / 2; //圆半径
        $y_x = $r;     //圆心X坐标
        $y_y = $r;     //圆心Y坐标

        for($x = 0;$x < $w;$x++){
            for($y = 0;$y < $h;$y++){
                $rgbColor = imagecolorat($this->image,$x,$y);
                if(((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))){
                    imagesetpixel($img,$x,$y,$rgbColor);
                }
            }
        }

        $this->image = $img;

        return $this;

    }


    /**
     * 获取图片宽度
     * @date (2022/4/11 18:42:41)
     * @return false|int
     * @author (WangDaBao)
     */
    public function getWidth()
    {

        return imagesx($this->image);
    }


    /**
     * 获取图片高度
     * @date (2022/4/11 18:42:34)
     * @return false|int
     * @author (WangDaBao)
     */
    public function getHeight()
    {

        return imagesy($this->image);
    }


    /**
     * 设置背景图片
     * @date (2022/4/11 16:49:55)
     * @param $background (背景图片绝对路径)
     * @return $this
     * @author (WangDaBao)
     */
    public function setBackground($background)
    {

        //  背景方法
        $backgroundInfo = getimagesize($background);

        //  设置保存路径
        $this->mime = $backgroundInfo["mime"];

        //
        $this->image_type = $backgroundInfo[2];

        //	获取方法名称
        $backgroundFun = 'imagecreatefrom'.image_type_to_extension($this->image_type,false);

        //	创建背景资源
        $background = $backgroundFun($background);

        //	背景宽度
        $this->backgroundWidth = imagesx($background);

        //	背景高度
        $this->backgroundHeight = imagesy($background);

        $this->image = imageCreatetruecolor($this->backgroundWidth,$this->backgroundHeight);

        $color = imagecolorallocate($this->image,0,0,0);

        imagefill($this->image,0,0,$color);

        //	颜色透明
        imageColorTransparent($this->image,$color);

        //	将背景图合并到背景
        imagecopyresampled(
            $this->image,
            $background,
            0,
            0,
            0,
            0,
            imagesx($background),
            imagesy($background),
            imagesx($background),
            imagesy($background)
        );
        imagedestroy($background);
        return $this;

    }


    /**
     * 填充文字
     * @date (2022/4/11 16:39:22)
     * @param $text (文字内容)
     * @param $left (距离左侧位置)
     * @param $top (距离顶部位置)
     * @param $fontPath (字体路径)
     * @param $fontSize (字体大小)
     * @param $fontColor (字体颜色)
     * @param $angle (倾斜角度)
     * @author (WangDaBao)
     */
    public function setText($text = "测试文字",$left = 0,$top = 0,$fontPath = null,$fontSize = null,$fontColor = null,$angle = null)
    {

        if(!$this->image){
            throw new Exception("请先调用setBackground方法设置背景图片");
        }

        $fontPath = $fontPath ? : getcwd()."/Uploads/fonts/simsun.ttc";

        if(!file_exists($fontPath)){
            throw new Exception("检测不到字体文件,请检查路径是否正确");
        }

        //  格式化颜色
        list($R,$G,$B) = explode(',',$fontColor ? : $this->fontColor);

        //  设置颜色
        $fontColor = imagecolorallocate($this->image,$R,$G,$B);

        //  校正左侧距离
        $left = $left < 0 ? $this->backgroundWidth - abs($left) : $left;

        //  校正顶部距离
        $top = $top < 0 ? $this->backgroundHeight - abs($top) : $top;

        imagettftext(
            $this->image,
            $fontSize ? : $this->fontSize,
            $angle ? : 0,
            $left,
            $top,
            $fontColor,
            $fontPath ? : $this->fontPath,
            $text);

        return $this;

    }


    /**
     * 填充图片
     * @date (2022/4/11 17:15:49)
     * @param string $url (图片路径或图片资源)
     * @param int $left (距离左侧像素)
     * @param int $top (距离顶部像素)
     * @param int $width (图片宽度)
     * @param int $height (图片高度)
     * @param int $opacity (透明度)
     * @param bool $expedite (此图片是否需要加速处理)
     * @return $this
     * @author (WangDaBao)
     */
    public function setImage($url = "",$left = 0,$top = 0,$width = 100,$height = 100,$opacity = 100,$expedite=false)
    {

        if(!$this->image){
            throw new Exception("请先调用setBackground方法设置背景图片");
        }

        [$res,$resWidth,$resHeight,$mine] = $this->check_file($url,$expedite);

        //	建立画板 ，缩放图片至指定尺寸
        $canvas = imagecreatetruecolor($width,$height);

        //	创建透明背景色，主要127参数，其他可以0-255，因为任何颜色的透明都是透明
        $color = imagecolorallocatealpha($canvas,255,255,255,127);

        //	指定颜色为透明（做了移除测试，发现没问题）
        imagecolortransparent($canvas,$color);

        //	保留透明颜色
        imagesavealpha($canvas,true);

        //	填充图片颜色
        imagefill($canvas,0,0,$color);

        //关键函数，
        //参数（目标资源，源，目标资源的开始坐标x,y, 源资源的开始坐标x,y,目标资源的宽高w,h,源资源的宽高w,h）
        imagecopyresampled(
            $canvas,
            $res,
            0,
            0,
            0,
            0,
            $width,
            $height,
            $resWidth,
            $resHeight
        );

        $left = $left < 0 ? $this->backgroundWidth - abs($left) - $width : $left;
        $top  = $top < 0 ? $this->backgroundHeight - abs($top) - $height : $top;

        if(strpos($mine,"png")!==false){

            imagecopy(
                $this->image,
                $canvas,
                $left,
                $top,
                0,
                0,
                $width,
                $height
            );

        }else{

            //	放置图像
            imagecopymerge(
                $this->image,
                $canvas,
                $left,
                $top,
                0,
                0,
                $width,     //	宽度
                $height,    //	高度
                $opacity    //	透明度
            );

        }
        imagedestroy($canvas);
        imagedestroy($res);
        return $this;

    }


    /**
     *  将字符串按照长度分割
     */
    public function mbStrSplit($string,$len = 1)
    {
        $start  = 0;
        $strlen = mb_strlen($string);
        while($strlen){
            $array[] = mb_substr($string,$start,$len,"utf8");
            $string  = mb_substr($string,$len,$strlen,"utf8");
            $strlen  = mb_strlen($string);
        }
        return $array;
    }


    /**
     * 输出图片到网页
     * @date (2022/4/11 17:18:22)
     * @author (WangDaBao)
     */
    public function show()
    {

        header("content-type: ".$this->mime);

        if(!$this->image){
            throw new Exception("图片资源为空");
        }

        if(strpos($this->mime,"jpeg")!==false){
            imagejpeg($this->image);
        }

        if(strpos($this->mime,"png")!==false){
            imagepng($this->image);
        }

        if(strpos($this->mime,"gif")!==false){
            imagegif($this->image);
        }

        //  释放图片资源
        imagedestroy($this->image);

        $this->saveStatus = false;

        return $this;
    }


    /**
     * 保存图片
     * @date (2022/4/11 17:32:49)
     * @param $filename (图片存放路径)
     * @param int $compression (图片质量)
     * @param null $permissions
     * @author (WangDaBao)
     */
    public function save($filename,$compression = 75)
    {

        if(!$filename){
            throw new Exception("保存路径不能为空");
        }

        if(!$this->saveStatus){
            throw new  Exception("请关闭输出到浏览器,再保存");
        }

        if(strpos($this->mime,"jpeg")!==false){
            imagejpeg($this->image,$filename,$compression);
        }

        if(strpos($this->mime,"png")!==false){
            imagepng($this->image,$filename);
        }

        if(strpos($this->mime,"gif")!==false){
            imagegif($this->image,$filename);
        }

        if(!file_exists($filename)){
            throw new Exception("图片生成失败");
        }

        //  释放掉图片资源
        imagedestroy($this->image);

        return true;
    }


    /**
     * 重置图片高度
     * @date (2022/4/11 18:42:17)
     * @param $height
     * @author (WangDaBao)
     */
    public function resizeToHeight($height)
    {

        $ratio = $height / $this->getHeight();
        $width = $this->getWidth() * $ratio;
        $this->resize2($width,$height);
    }


    /**
     * 重置图片宽高 PNG
     * @date (2022/4/11 18:42:49)
     * @param $width
     * @param $height
     * @author (WangDaBao)
     */
    function resize2($width,$height)
    {
        $new_image = imagecreatetruecolor($width,$height);
        if($this->image_type==IMAGETYPE_GIF || $this->image_type==IMAGETYPE_PNG){
            $current_transparent = imagecolortransparent($this->image);
            if($current_transparent!=-1){
                $transparent_color   = imagecolorsforindex($this->image,$current_transparent);
                $current_transparent = imagecolorallocate($new_image,$transparent_color['red'],$transparent_color['green'],$transparent_color['blue']);
                imagefill($new_image,0,0,$current_transparent);
                imagecolortransparent($new_image,$current_transparent);
            }elseif($this->image_type==IMAGETYPE_PNG){
                imagealphablending($new_image,false);
                $color = imagecolorallocatealpha($new_image,0,0,0,127);
                imagefill($new_image,0,0,$color);
                imagesavealpha($new_image,true);
            }
        }
        imagecopyresampled($new_image,$this->image,0,0,0,0,$width,$height,$this->getWidth(),$this->getHeight());
        $this->image = $new_image;
    }


    /**
     * 重置图片宽度
     * @date (2022/4/11 18:42:58)
     * @param $width
     * @author (WangDaBao)
     */
    public function resizeToWidth($width)
    {
        if($this->getWidth() < $width){
            $width = $this->getWidth();
        }
        $ratio  = $width / $this->getWidth();
        $height = $this->getheight() * $ratio;
        $this->resize2($width,$height);
    }


    /**
     * @date (2022/4/11 18:43:05)
     * @param $scale
     * @author (WangDaBao)
     */
    public function scale($scale)
    {
        $width  = $this->getWidth() * $scale / 100;
        $height = $this->getheight() * $scale / 100;
        $this->resize2($width,$height);
    }


    /**
     * 重置图片宽高
     * @date (2022/4/11 18:43:12)
     * @param $width
     * @param $height
     * @author (WangDaBao)
     */
    public function resize($width,$height)
    {

        $new_image = imagecreatetruecolor($width,$height);
        imagecopyresampled($new_image,$this->image,0,0,0,0,$width,$height,$this->getWidth(),$this->getHeight());
        $this->image = $new_image;

    }

    /**
     * 处理图片
     * @param string $url
     * @return array
     */
    private function check_file(string $url,$expedite=false)
    {
        $preg = "/^http(s)?:\\/\\/.+/";
        if(preg_match($preg,$url) && $expedite){
            [$image,$mime] = $this->getImage($url);
            $im = imagecreatefromstring($image);
            $width = imagesx($im);
            $height = imagesy($im);
        }else{
            $is_string = is_string($url);
            $info = $is_string?getimagesize($url):getimagesizefromstring($url);
            $function = $is_string?'imagecreatefrom'.image_type_to_extension($info[2],false):'imagecreatefromstring';
            $im = $function($url);
            $width = $info? $info[0] : 0;
            $height = $info ? $info[1] : 0;
            $mime = $info ? $info['mime'] : '';
        }

        return [$im,$width,$height,$mime];
    }
    /**
     * 输出图片二进制字符串
     * @return false|string
     */
    public function getImageString()
    {
        ob_start();
        imagepng($this->image);
        $image_string = ob_get_contents();
        ob_end_clean();
        imagedestroy($this->image);
        return $image_string;
    }

    /**
     * 获取远程图片加速
     * @param string $url
     * @return array
     */
    public function getImage(string $url )
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_ENCODING, ""); //加速 这个地方留空就可以了
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        $http_code = curl_getinfo($ch);
        curl_close($ch);
        return [$output,$http_code['content_type']??''];
    }
}
